package net.bithappens.hnqe.query;

import java.net.URI;
import java.net.URISyntaxException;

import net.bithappens.hnqe.IllegalParamException;
import net.bithappens.hnqe.graph.EntryValue;
import net.bithappens.hnqe.query.ConstraintCompare.ConstraintType;
import net.bithappens.hnqe.query.ConstraintMath.MathCompare;
import net.bithappens.hnqe.query.Link.MatchType;

public class QueryFactory {

	private int nodeIdCount = 0;
	private int valueNodeIdCount = 0;
	private int relationIdCount = 0;
	
	
	public Node newNode(URI uri, String typeId){
		try {
			return new Node("N"+nodeIdCount++, uri, typeId);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	public Node newNode(String uri, String typeId) throws URISyntaxException{
		try {
			return new Node("N"+nodeIdCount++, new URI(uri), typeId);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	public Node newNode(URI uri) {
		try {
			return new Node("N"+nodeIdCount++, uri, null);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	public Node newNode(String typeId) {
		try {
			return new Node("N"+nodeIdCount++, null, typeId);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	
	public Node newNode() throws URISyntaxException{
		try {
			return new Node("N"+nodeIdCount++, null, null);
		} catch (InvalidIdException e) {}
		return null;
	}

	
	
	
	public ValueNode newValueNode(URI uri, Object value) throws IllegalParamException{
		
		EntryValue entryVal = EntryValue.createEntryValue(value);
		
		try {
			return new ValueNode("VN"+valueNodeIdCount++, uri, entryVal);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	public ValueNode newValueNode(String uri, Object value) throws URISyntaxException, IllegalParamException{
		
		EntryValue entryVal = EntryValue.createEntryValue(value);
		
		try {
			return new ValueNode("VN"+valueNodeIdCount++, new URI(uri), entryVal);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	public ValueNode newValueNode(URI uri){
		try {
			return new ValueNode("VN"+valueNodeIdCount++, uri, null);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	public ValueNode newValueNode(Object value) throws IllegalParamException{
		EntryValue entryVal = EntryValue.createEntryValue(value);
		
		try {
			return new ValueNode("VN"+valueNodeIdCount++, null, entryVal);
		} catch (InvalidIdException e) {}
		return null;	
	}
	
	
	public ValueNode newValueNode() throws URISyntaxException{
		try {
			return new ValueNode("VN"+valueNodeIdCount++, null, null);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	
	
	
	
	
	public Relation newRelation(URI uri, String typeId){
		try {
			return new Relation("R"+relationIdCount++, uri, typeId);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	public Relation newRelation(String uri, String typeId) throws URISyntaxException{
		try {
			return new Relation("R"+relationIdCount++, new URI(uri), typeId);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	public Relation newRelation(URI uri) {
		try {
			return new Relation("R"+relationIdCount++, uri, null);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	public Relation newRelation(String typeId) {
		try {
			return new Relation("R"+relationIdCount++, null, typeId);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	public Relation newRelation() throws URISyntaxException{
		try {
			return new Relation("R"+relationIdCount++, null, null);
		} catch (InvalidIdException e) {}
		return null;
	}
	
	
	
	
	public static AtomConstant newConstant(Object value) throws IllegalParamException{
		
		EntryValue entryVal = EntryValue.createEntryValue(value);
		
		return new AtomConstant(entryVal);
				
	}
	
	public static Constraint EQUAL(Atom atom1, Atom atom2) throws Exception{
		return new ConstraintCompare(atom1, ConstraintType.EQUAL, atom2);
	}
	
	public static Constraint GREATHER(Atom atom1, Atom atom2) throws Exception{
		return new ConstraintCompare(atom1, ConstraintType.GREATHER, atom2);
	}
	
	public static Constraint GREATHEREQUAL(Atom atom1, Atom atom2) throws Exception{
		return new ConstraintCompare(atom1, ConstraintType.GREATHEREQUAL, atom2);
	}
	
	public static Constraint LESS(Atom atom1, Atom atom2) throws Exception{
		return new ConstraintCompare(atom1, ConstraintType.LESS, atom2);
	}
	
	public static Constraint LESSEQUAL(Atom atom1, Atom atom2) throws Exception{
		return new ConstraintCompare(atom1, ConstraintType.LESSEQUAL, atom2);
	}
	
	public static Constraint MATCH(Atom valueString, Atom pattern) throws Exception{
		return new ConstraintCompare(valueString, ConstraintType.MATCHREGEX, pattern);
	}
	
	
	public static ConstraintMath MATH_EQUAL(Atom value) throws Exception{
		return new ConstraintMath(value, MathCompare.EQUAL);
	}
	
	public static ConstraintMath MATH_GEATHER(Atom value) throws Exception{
		return new ConstraintMath(value, MathCompare.GREATHER);
	}
	
	public static ConstraintMath MATH_GREATHEREQUAL(Atom value) throws Exception{
		return new ConstraintMath(value, MathCompare.GREATHEREQUAL);
	}
	
	public static ConstraintMath MATH_LESS(Atom value) throws Exception{
		return new ConstraintMath(value, MathCompare.LESS);
	}
	
	public static ConstraintMath MATH_LESSEQUAL(Atom value) throws Exception{
		return new ConstraintMath(value, MathCompare.LESSEQUAL);
	}


	public static Link EXACTMATCH(Relation relation, RelationMember... members) throws IllegalParamException{
		return new Link(relation, MatchType.EXACTMATCH, members);
	}
	
	public static Link ANYCONNECTION(Relation relation, RelationMember... members) throws IllegalParamException{
		return new Link(relation, MatchType.ANYCONNECTION, members);
	}
	
	public static LogicalOperation AND(QueryTree... params) throws IllegalParamException{
		return LogicalOperation.AND(params);
	}
	
	public static LogicalOperation OR(QueryTree... params) throws IllegalParamException{
		return LogicalOperation.OR(params);
	}
	
	public static LogicalOperation NOT(QueryTree params){
		return LogicalOperation.NOT(params);
	}
	
}
